package com.wondertek.onvif.controller;

import com.wondertek.onvif.common.ResultBean;
import com.wondertek.onvif.service.StreamingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * 流媒体控制器
 * 
 * @author wondertek
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/streaming")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
public class StreamingController {

    private static final Logger log = LoggerFactory.getLogger(StreamingController.class);
    
    private final StreamingService streamingService;

    /**
     * 开始播放通道视频流
     * 
     * @param channelId 通道ID
     * @param quality 视频质量 (high/medium/low)
     * @return 流媒体会话信息
     */
    @PostMapping("/channels/{channelId}/start")
    public ResultBean<Map<String, Object>> startStream(
            @PathVariable Long channelId,
            @RequestParam(defaultValue = "medium") String quality) {
        try {
            String sessionId = streamingService.startStream(channelId, quality);
            Map<String, Object> data = Map.of(
                "success", true,
                "sessionId", sessionId,
                "message", "视频流启动成功"
            );
            return ResultBean.success(data, "视频流启动成功");
        } catch (Exception e) {
            log.error("启动视频流失败", e);
            Map<String, Object> data = Map.of(
                "success", false,
                "message", "启动视频流失败: " + e.getMessage()
            );
            return ResultBean.error("启动视频流失败: " + e.getMessage(), data);
        }
    }

    /**
     * 停止播放通道视频流
     * 
     * @param channelId 通道ID
     * @param sessionId 会话ID
     * @return 停止结果
     */
    @PostMapping("/channels/{channelId}/stop")
    public ResultBean<Map<String, Object>> stopStream(
            @PathVariable Long channelId,
            @RequestParam String sessionId) {
        try {
            streamingService.stopStream(channelId, sessionId);
            Map<String, Object> data = Map.of(
                "success", true,
                "message", "视频流停止成功"
            );
            return ResultBean.success(data, "视频流停止成功");
        } catch (Exception e) {
            log.error("停止视频流失败", e);
            Map<String, Object> data = Map.of(
                "success", false,
                "message", "停止视频流失败: " + e.getMessage()
            );
            return ResultBean.error("停止视频流失败: " + e.getMessage(), data);
        }
    }

    /**
     * 获取通道的MJPEG视频流
     * 
     * @param channelId 通道ID
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    @GetMapping(value = "/channels/{channelId}/mjpeg", produces = "multipart/x-mixed-replace; boundary=frame")
    public void getMjpegStream(
            @PathVariable Long channelId,
            @RequestParam(defaultValue = "medium") String quality,
            HttpServletResponse response) throws IOException {
        
        response.setContentType("multipart/x-mixed-replace; boundary=frame");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Connection", "keep-alive");
        
        try {
            streamingService.streamMjpeg(channelId, quality, response.getOutputStream());
        } catch (Exception e) {
            log.error("MJPEG流传输失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 获取通道快照
     * 
     * @param channelId 通道ID
     * @return 快照图片
     */
    @GetMapping(value = "/channels/{channelId}/snapshot", produces = MediaType.IMAGE_JPEG_VALUE)
    public ResponseEntity<byte[]> getSnapshot(@PathVariable Long channelId) {
        try {
            byte[] snapshot = streamingService.getSnapshot(channelId);
            if (snapshot != null && snapshot.length > 0) {
                return ResponseEntity.ok()
                    .contentType(MediaType.IMAGE_JPEG)
                    .body(snapshot);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            log.error("获取快照失败", e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 获取通道的实时视频流（SSE方式）
     * 
     * @param channelId 通道ID
     * @param quality 视频质量
     * @return SSE发射器
     */
    @GetMapping(value = "/channels/{channelId}/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter getStreamSse(
            @PathVariable Long channelId,
            @RequestParam(defaultValue = "medium") String quality) {
        
        SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
        
        try {
            streamingService.streamSse(channelId, quality, emitter);
        } catch (Exception e) {
            log.error("SSE流传输失败", e);
            emitter.completeWithError(e);
        }
        
        return emitter;
    }

    /**
     * 获取活跃的流媒体会话列表
     * 
     * @return 活跃会话列表
     */
    @GetMapping("/sessions")
    public ResultBean<Map<String, Object>> getActiveSessions() {
        try {
            Map<String, Object> sessions = streamingService.getActiveSessions();
            return ResultBean.success(sessions, "获取活跃会话列表成功");
        } catch (Exception e) {
            log.error("获取活跃会话列表失败", e);
            return ResultBean.error("获取活跃会话列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取指定通道的流媒体会话信息
     * 
     * @param channelId 通道ID
     * @return 会话信息
     */
    @GetMapping("/channels/{channelId}/sessions")
    public ResultBean<Map<String, Object>> getChannelSessions(@PathVariable Long channelId) {
        try {
            Map<String, Object> sessions = streamingService.getChannelSessions(channelId);
            return ResultBean.success(sessions, "获取通道会话信息成功");
        } catch (Exception e) {
            log.error("获取通道会话信息失败", e);
            return ResultBean.error("获取通道会话信息失败: " + e.getMessage());
        }
    }

    /**
     * 停止所有流媒体会话
     * 
     * @return 停止结果
     */
    @PostMapping("/sessions/stop-all")
    public ResultBean<Map<String, Object>> stopAllSessions() {
        try {
            int stoppedCount = streamingService.stopAllSessions();
            Map<String, Object> data = Map.of(
                "success", true,
                "stoppedCount", stoppedCount,
                "message", "已停止 " + stoppedCount + " 个流媒体会话"
            );
            return ResultBean.success(data, "停止所有会话成功");
        } catch (Exception e) {
            log.error("停止所有会话失败", e);
            Map<String, Object> data = Map.of(
                "success", false,
                "message", "停止所有会话失败: " + e.getMessage()
            );
            return ResultBean.error("停止所有会话失败: " + e.getMessage(), data);
        }
    }

    /**
     * 获取流媒体统计信息
     * 
     * @return 统计信息
     */
    @GetMapping("/statistics")
    public ResultBean<Map<String, Object>> getStreamingStatistics() {
        try {
            Map<String, Object> statistics = streamingService.getStreamingStatistics();
            return ResultBean.success(statistics, "获取流媒体统计信息成功");
        } catch (Exception e) {
            log.error("获取流媒体统计信息失败", e);
            return ResultBean.error("获取流媒体统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 检查通道是否支持流媒体
     * 
     * @param channelId 通道ID
     * @return 支持情况
     */
    @GetMapping("/channels/{channelId}/support")
    public ResultBean<Map<String, Object>> checkStreamingSupport(@PathVariable Long channelId) {
        try {
            boolean supported = streamingService.isStreamingSupported(channelId);
            Map<String, Object> data = Map.of(
                "supported", supported,
                "message", supported ? "支持流媒体播放" : "不支持流媒体播放"
            );
            return ResultBean.success(data, "检查流媒体支持完成");
        } catch (Exception e) {
            log.error("检查流媒体支持失败", e);
            Map<String, Object> data = Map.of(
                "supported", false,
                "message", "检查失败: " + e.getMessage()
            );
            return ResultBean.error("检查流媒体支持失败: " + e.getMessage(), data);
        }
    }

    /**
     * 获取通道的流媒体URL
     * 
     * @param channelId 通道ID
     * @param quality 视频质量
     * @return 流媒体URL信息
     */
    @GetMapping("/channels/{channelId}/urls")
    public ResultBean<Map<String, Object>> getStreamUrls(
            @PathVariable Long channelId,
            @RequestParam(defaultValue = "medium") String quality) {
        try {
            Map<String, Object> urls = streamingService.getStreamUrls(channelId, quality);
            return ResultBean.success(urls, "获取流媒体URL成功");
        } catch (Exception e) {
            log.error("获取流媒体URL失败", e);
            Map<String, Object> data = Map.of(
                "success", false,
                "message", "获取流媒体URL失败: " + e.getMessage()
            );
            return ResultBean.error("获取流媒体URL失败: " + e.getMessage(), data);
        }
    }
}